package wl

import (
	"crypto/sha256"
	"fmt"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"
	"github.com/bwmarrin/snowflake"
	"github.com/go-redis/redis"
	"github.com/jinzhu/gorm"
	"github.com/json-iterator/go"
	"github.com/syyongx/php2go"
	"math/rand"
	"strconv"
	"time"
)


var (
	Host string
	Port string
	PassWord string
	DB *gorm.DB
	Redis *redis.Client
	MachineID string   //唯一一个字符串
	UnqNode *snowflake.Node
	UploadPath string
)
type CodeType struct {
	Click int
	Error int
	Success int
	Auth int
	Login int
}
var ResponseCode =CodeType{Click:401,Error:0,Auth:400,Success:200,Login:402}

//成功消息结构
type Succes struct {
	Code int
	Message interface{}
}
//失败消息结构
type Error struct {
	code int
	message interface{}
}
//访问消息结构
type Click struct {
	Code int
	Message interface{}
}
//权限消息结构
type Auth struct {
	Code int
	Message interface{}
}
//登陆结构
type Login struct {
	Code int
	Message interface{}
}


func init()  {
	Host=C("Redis::Host")
	Port=C("Redis::Port")
	PassWord=C("Redis::PassWord")


	Redis = redis.NewClient(&redis.Options{
		Addr:    Host+":"+Port,
		Password: PassWord,
		DB:       0,
	})
	var err error
	pong, err := Redis.Ping().Result()
	fmt.Println(pong, err)

	MakeMachineID()//生成机器码

	//加载  id 生成器
	UnqNode,err  = snowflake.NewNode(1)
	if err != nil {
		panic(err)

	}

	UploadPath=C("Upload::Path")

}


func GormConnect(){

	SqlDriver:=C("dev::Driver")
	SqluserName:=C("dev::userName")
	SqlPassword:=C("dev::Password")
	SqlHost:=C("dev::Host")
	SqlDbName:=C("dev::DbName")
	SqlPort:=C("dev::Port")

	//dataSource:=fmt.Printf("%d:123456@tcp(192.168.0.9:3306)/cloud?charset=utf8",SqluserName)
	dataSource:=fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8", SqluserName,SqlPassword,SqlHost,SqlPort,SqlDbName)
	fmt.Println(dataSource)
	var err error
	DB, err = gorm.Open(SqlDriver, dataSource)
	if err != nil {
		fmt.Println("连接数据库语句",dataSource)
		panic(err)
		panic("数据库连接失败!")

	}else{
		fmt.Println("连接数据库成功!")
	}

	DB.DB().SetMaxIdleConns(100)
	DB.DB().SetMaxOpenConns(1000)
	DB.DB().SetConnMaxLifetime(time.Second)

	DB.LogMode(true)  //
	DB.SingularTable(true)

	DB.Callback().Create().Replace("gorm:update_time_stamp",updateTimeStampForCreateCallback)
	DB.Callback().Update().Replace("gorm:update_time_stamp",updateTimeStampForUpdateCallback)
}

// 注册更新钩子在持久化之前
func updateTimeStampForUpdateCallback(scope *gorm.Scope) {
	if _, ok := scope.Get("gorm:update_column"); !ok {
		scope.SetColumn("UpdatedAt", time.Now().Unix())
	}
}

// // 注册新建钩子在持久化之前
func updateTimeStampForCreateCallback(scope *gorm.Scope) {

	if !scope.HasError() {
		nowTime := time.Now().Unix()
		if createTimeField, ok := scope.FieldByName("CreatedAt"); ok {
			if createTimeField.IsBlank {
				createTimeField.Set(nowTime)
			}
		}

		if modifyTimeField, ok := scope.FieldByName("UpdatedAt"); ok {
			if modifyTimeField.IsBlank {
				modifyTimeField.Set(nowTime)
			}
		}
	}
}
//获取配置文件参数
func C(key string) string{
	value:=beego.AppConfig.Strings(key)
	if !php2go.Empty(value) {
		return value[0]
	}else{
		return ""
	}
}

//获默认分页个数
func Limit() int{
	limit:=C("limit")
	limitInt, _ := strconv.Atoi(limit)
	return limitInt
}



func WLRedis() *redis.Client   {

	return Redis
}

func RedisGet(key string) []byte {
	 valueByte,_:=Redis.Get(key).Bytes()
	 return valueByte
}
func RedisSet(key string,value interface{},timeSec time.Duration)  {
	jsonValue,_:=jsoniter.Marshal(value)
	var timeMin time.Duration=60*timeSec*time.Second

	Redis.Set(key, string(jsonValue), timeMin)

}

func AjaxSuccess(a interface{})  (Succes){
	return Succes{ResponseCode.Success,a}
}

func AjaxError(a interface{}) (interface{}){

	 return Succes{ResponseCode.Error,a}
}

func AjaxClick(a interface{}) (Click){

	return Click{ResponseCode.Click,a}
}
func AjaxAuth(a interface{}) (interface{}){

	return Auth{ResponseCode.Auth,a}
}

func AjaxLogin(a interface{}) (Login){

	return Login{ResponseCode.Login,a}
}

func AJAX(ctx *context.Context,info interface{})  {
	ctx.Output.JSON(info,true,false)
	panic(beego.ErrAbort)
}





//sha256 加密
func WlSha256 (strings string) string{
	h := sha256.New()
	h.Write([]byte(strings))
	bs := h.Sum(nil)

	return fmt.Sprintf("%x",bs)
}

//string 转int
func ToInt(strings string)  int{

	info, err := strconv.Atoi(strings)

	if err!=nil{
		panic("强转发生错误!")
	}

	return info

}
//string 转int64
func ToInt64(strings string)  int64{

	info,err := strconv.ParseInt(strings,10,64)

	if err!=nil{
		panic("强转发生错误!")
	}

	return info

}

//string 转int
func ToString(num int)  string{

	randString := strconv.Itoa(num)

	return randString

}
func MakeMachineID()  {
	rand.Seed(time.Now().UnixNano())
	MachineID=php2go.Uniqid("")
}

func UniqStr() string {
	randNum := rand.Int()
	randString := ToString(randNum)
	unqIDString:=ToString(UniqID())

	return  php2go.Md5(randString+MachineID+unqIDString)

}

func UniqID() int {

	id:=UnqNode.Generate()
	Intid:=int(id)

	return Intid

}